package com.example.itcacp.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.itcacp.entity.BrowseHistory;
import com.example.itcacp.entity.Like;
import com.example.itcacp.repository.mybatis.BrowseHistoryMapper;
import com.example.itcacp.repository.mybatis.LikeMapper;
import jakarta.annotation.Resource;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 推荐系统的数据构建与处理
 * */
@Service
public class DataPreparationService {

    @Resource
    BrowseHistoryMapper browseHistoryMapper;  // 浏览记录行为
    @Resource
    private  LikeMapper likeMapper;    // 点赞行为
    @Resource
    private RedisService redisService;   // 缓存服务


    // 本地缓存，用于减少 Redis 访问
    private final Map<Long, Map<Long, Integer>> localCache = new ConcurrentHashMap<> ();
    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    /**
     * 获取用户-内容矩阵
     */
    public Map<Long, Map<Long, Integer>> buildUserItemMatrix() {
        // 获取所有用户ID
        List<Long> userIds = likeMapper.getAllUserIds();
        Map<Long, Map<Long, Integer>> matrix = new HashMap<>();

        // 批量获取用户数据
        for (Long userId : userIds) {
            matrix.put(userId, getUserItems(userId));
        }

        return matrix;
    }


    /**
     * 获取单个用户的内容操作记录
     */
    public Map<Long, Integer> getUserItems(Long userId) {
        // 优先从本地缓存获取
        if (localCache.containsKey(userId)) {
            return localCache.get(userId);
        }
        // 从 Redis 获取
        Map<String, Integer> redisItems = redisService.getUserItems(userId);
        if (!redisItems.isEmpty()) {
            Map<Long, Integer> result = convertMap(redisItems);
            localCache.put(userId, result);
            return result;
        }
        // Redis 没有则从数据库加载，并异步更新缓存
        Map<Long, Integer> dbItems = loadItemsFromDb(userId);
        executor.submit(() -> updateCache(userId, dbItems));
        return dbItems;
    }

    /**
     * 从数据库加载用户内容操作记录
     */
    private Map<Long, Integer> loadItemsFromDb(Long userId) {
        LambdaQueryWrapper<Like> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Like::getUserId, userId);
        List<Like> likes = likeMapper.selectList(queryWrapper);

        return likes.stream()
                .collect(Collectors.toMap(Like::getTargetId, like -> 1, (a, b) -> b));
    }

    /**
     * 更新 Redis 缓存
     */
    private void updateCache(Long userId, Map<Long, Integer> items) {
        Map<String, Integer> stringKeyMap = new HashMap<>();
        for (Map.Entry<Long, Integer> entry : items.entrySet()) {
            stringKeyMap.put(entry.getKey().toString(), entry.getValue());
        }
        redisService.setUserItems(userId, stringKeyMap);
    }

    /**
     * 转换 Map 键类型
     */
    private Map<Long, Integer> convertMap(Map<String, Integer> map) {
        return map.entrySet().stream()
                .collect( Collectors.toMap(
                        e -> Long.parseLong(e.getKey()),
                        Map.Entry::getValue,
                        (a, b) -> b,
                        HashMap::new
                ));
    }

    /**
     * 处理用户新的点赞操作，更新缓存
     */
    @Transactional
    public void handleNewLike(Long userId, Long contentId) {
        // 先检查是否已点赞
        LambdaQueryWrapper<Like> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Like::getUserId, userId)
                .eq(Like::getTargetId, contentId);

        Like existingLike = likeMapper.selectOne(queryWrapper);
        if (existingLike == null) {
            // 新增点赞记录
            Like like = new Like();
            like.setUserId(userId);
            like.setTargetId(contentId);
            likeMapper.insert(like);
        } else {
            // 已点赞，更新时间
            existingLike.setCreated_at (new Timestamp ( System.currentTimeMillis () ).toLocalDateTime ());
            likeMapper.updateById(existingLike);
        }

        // 更新本地缓存
        localCache.computeIfAbsent(userId, k -> new HashMap<>())
                .put(contentId, 1);

        // 异步更新 Redis
        executor.submit(() -> redisService.setUserItem(userId, contentId, 1));
    }

    /**
     * 处理用户取消点赞操作，更新缓存
     */
    @Transactional
    public void handleCancelLike(Long userId, Long contentId) {
        // 删除点赞记录
        LambdaQueryWrapper<Like> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Like::getUserId, userId)
                .eq(Like::getTargetId, contentId);
        likeMapper.delete(queryWrapper);

        // 更新本地缓存
        localCache.computeIfPresent(userId, (k, v) -> {
            v.remove(contentId);
            return v;
        });

        // 异步更新 Redis
        executor.submit(() -> {
            if (redisService.hasUserItems(userId)) {
                redisService.getUserItems(userId).remove(contentId.toString());
            }
        });
    }





    /**
     * 构建基于浏览记录的用户-内容矩阵：用于项目推荐
     * @return 用户-内容矩阵
     */
    public Map<Long, Map<Long, Integer>> buildUserBrowseMatrix() {
        Map<Long, Map<Long, Integer>> userItemMatrix = new HashMap<>();

        // 获取所有用户关于项目的浏览记录
        List<BrowseHistory> allHistories = browseHistoryMapper.selectListByType ( "PROJECT" );
//        // 获取所有用户的浏览记录
//        List<BrowseHistory> allHistories = browseHistoryMapper.selectList(null);

        // 构建矩阵
        for (BrowseHistory history : allHistories) {
            Long userId = history.getUserId();
            Long contentId = history.getTargetId();

            // 获取或创建用户的操作记录
            userItemMatrix.computeIfAbsent(userId, k -> new HashMap<>())
                    .merge(contentId, 1, Integer::sum);
        }

        return userItemMatrix;
    }
}
